package com.sunwayhorizo.health.business.clinic.emr.document;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.ejb.Stateless;

import org.jboss.seam.Component;
import org.jboss.seam.annotations.Name;

import com.sunwayhorizo.health.business.base.BaseManager;
import com.sunwayhorizo.health.business.clinic.emr.document.query.DocumentQueryLocal;
import com.sunwayhorizo.health.business.clinic.emr.emrmanager.EmrManagerLocal;
import com.sunwayhorizo.health.business.clinic.emr.observation.ObservationManagerLocal;
import com.sunwayhorizo.health.business.dto.ResultsDTO;
import com.sunwayhorizo.health.business.dto.clinic.emr.document.EmrDiagnosisDTO;
import com.sunwayhorizo.health.business.dto.clinic.emr.document.EmrModifyLogDTO;
import com.sunwayhorizo.health.business.dto.clinic.emr.document.EmrWriterDTO;
import com.sunwayhorizo.health.common.DataTypeUtil;
import com.sunwayhorizo.health.common.DateUtil;
import com.sunwayhorizo.health.common.ListUtil;
import com.sunwayhorizo.health.common.StrUtil;
import com.sunwayhorizo.health.hl7.common.Hl7Exception;
import com.sunwayhorizo.health.hl7.datatypes.CS;
import com.sunwayhorizo.health.hl7.datatypes.ED;
import com.sunwayhorizo.health.hl7.persistent.RimCoreEds;
import com.sunwayhorizo.health.hl7.rim.ActParticipation;
import com.sunwayhorizo.health.hl7.rim.ActRelationship;
import com.sunwayhorizo.health.hl7.rim.ControlAct;
import com.sunwayhorizo.health.hl7.rim.Document;
import com.sunwayhorizo.health.hl7.rim.Observation;
import com.sunwayhorizo.health.hl7.rim.Role;
import com.sunwayhorizo.health.hl7.vocabulary.ActRelationshipType;
import com.sunwayhorizo.health.hl7.vocabulary.Direction;
import com.sunwayhorizo.health.hl7.vocabulary.ParticipationType;

/**
 * @ClassName InpatientRecordsManager <br>
 * @PackageName com.sunwayhorizo.health.business.emr.document <br>
 * @Description 电子病历，入院记录管理，单次书写 <br>
 * @Author jinzw <br>
 * @Date 2010-03-07 <br>
 * @Version 1.0 <br>
 * @ModifiedDesc <br>
 * @ModifiedDate <br>
 * @ModifiedBy <br>
 * @Copyright 2010-2020 北京三维海容 All Rights Reserved. <br>
 */
@Stateless
@Name(value = "InpatientRecordsManager")
public class InpatientRecordsManager extends BaseManager implements InpatientRecordsManagerLocal
{

    private DocumentCommonManagerLocal ecm = (DocumentCommonManagerLocal) Component.getInstance("DocumentCommonManager");
    private DocumentQueryLocal documentQuery = (DocumentQueryLocal) Component.getInstance("DocumentQuery");
    private ObservationManagerLocal observationManager = (ObservationManagerLocal) Component.getInstance("ObservationManager");


    public ResultsDTO newDocument(EmrWriterDTO emr) throws Hl7Exception
    {

        if ((null == emr) || (null == emr.getRimRoleEmrWriterClassId()) || (null == emr.getClassCode())
                || (StrUtil.isEmpty(emr.getPatientRoleId())))
        {
            log.info("新增电子病历失败，数据为空");
            return getResultsDTO("新增电子病历失败，数据为空", false, null);
        }
          Document doc = null;
          //得到患者病历管理动作
//          EmrManagerLocal emrManer =(EmrManagerLocal)Component.getInstance("EmrManager");
//          Document document= emrManer.findEmrManagerByPatientId(emr.getPatientRoleId(), emr.getPatientNum());
          //该病历可以进行书写 
//          if(null != document && (!document.getStatusCode().code().toString().equals("5") || !document.getStatusCode().code().toString().equals("6"))) 
//          {
              // 创建书写动作
              String code = emr.getClassCode();
              doc = ecm.creatClinicalDocument(code);
              
              //给书写动作赋值
              doc = ecm.injectDtoToDoc(emr, doc); 
              
              //得到参与入院记录书写动作的所有角色
              Map<CS,Role> socopeMap = ecm.findWriteEmrParticiRole(emr);
              //构建Participation列表
              constructParticipationList(socopeMap,emr);
              
              //得到诊断动作集合
              List<Observation> obsList = null;
              if (ListUtil.isNotEmpty(emr.getEmrDiagnosisList()))
              {
                  obsList = ecm.findObservationList(emr);
              }
              //把所有的动作加入到List列表中，为与病历书写动作建立关系做准备
              if(ListUtil.isNotEmpty(obsList))
              {
                  for(Observation obs : obsList)
                  {
                      ActRelationship relat = getActFactory().newActRelationship();
                      relat.setTypeCode(ActRelationshipType.DIAG);
                      addRelationship(obs, relat, Direction.SOURCE);
                  }
              }
//              //书写跟病历管理建立关系
//              ActRelationship relat = getActFactory().newActRelationship();
//              relat.setTypeCode(ActRelationshipType.PRCN);
//              addRelationship(document, relat, Direction.SOURCE);
              
              // 创建ControlAct
              ControlAct control = newControlAct(doc); 
              
              //持久化ControlAct
              save(control);
              log.info("新增电子病历成功" + doc.getActId().toString());
//          } 
//          else 
//          {
//              //该患者病历已经关闭，不能在进行书写 
//              return getResultsDTO("该患者病历已经关闭，不能在进行书写 ", true, null);
//          }
         
       
        return getResultsDTO("新增电子病历成功", true, doc.getActId().toString());
    }


    @SuppressWarnings("rawtypes")
    public ResultsDTO delDocument(List ids) throws Hl7Exception
    {
        if (ListUtil.isEmpty(ids))
        {
            log.info("删除电子病历失败，数据为空");
            return getResultsDTO("删除电子病历失败，数据为空", false, null);
        }
        String rel = ecm.delDoc(ids);
        if ("-1".equals(rel))
        {
            log.info("删除电子病历失败");
            return getResultsDTO("删除电子病历失败", false, null);
        }
        log.info("删除电子病历成功");
        return getResultsDTO("删除电子病历成功", true, null);
    }


    public ResultsDTO updateDocument(EmrWriterDTO emr) throws Hl7Exception
    {
        if ((null == emr))
        {
            log.info("电子病历签名失败，EmrWriterDTO数据为空");
            return getResultsDTO("电子病历签名失败，EmrWriterDTO数据为空", false, null);
        }
        if (StrUtil.isEmpty(emr.getId()))
        {
            // 保存带签名
            return newDocument(emr);
        }
        else
        {
            //得到病历动作
            Document doc = baseQuery.findDocumentById(emr.getId());
            // 设置签名信息
            if (!emr.getSignature().equals("0") || !emr.getSignature().equals("1"))
            {
                ecm.setSignatureInfo(emr, doc); 
            }
            //修改病历基本信息
            modifyEmrBaseInfo(emr,doc);
            // 加入诊断信息
            if (ListUtil.isNotEmpty(emr.getEmrDiagnosisList()))
            {
                ecm.setRelationship(doc, emr); 
            }
            em.merge(doc);
           
            log.info("电子病历签名成功");
            return getResultsDTO("电子病历签名成功", true, doc.getActId());
        }
    }

    public ResultsDTO findDocument(String emrClassRoleId) throws Hl7Exception
    {
        if (StrUtil.isEmpty(emrClassRoleId))
        {
            log.info("病历分类ID为空，没有找到该病历");
            return getResultsDTO("病历分类ID为空，没有找到该病历", false, null);
        }
        Document doc = ecm.findDoc(emrClassRoleId);
        EmrWriterDTO result = ecm.convertDocToDto(doc);
        log.info("查询电子病历成功");
        return getResultsDTO("查询电子病历成功", true, result);
    }


    @SuppressWarnings("unchecked")
    public ResultsDTO findDocumentByPatientId(String patientID,String patientNum) throws Hl7Exception
    {
        if (StrUtil.isEmpty(patientID))
        {
            log.info("患者ID为空，不能进行查询");
            return getResultsDTO("患者ID为空，不能进行查询 ", true, null);
        }
        List<Object> list = documentQuery.findEmrByPatientID(patientID, null,patientNum);
        if (ListUtil.isEmpty(list))
        {
            log.info("患者没有已书写的病历");
            return getResultsDTO("患者没有已书写的病历 ", true, null);
        }
        List<EmrWriterDTO> emrWriterList = ecm.convertDtoToList(list);

        log.info("获取患者病历成功");
        return getResultsDTO("获取患者病历成功 ", true, emrWriterList);
    }


    @SuppressWarnings("unchecked")
    public ResultsDTO findClassDocumentByPatient(String classCode, String patientID,String patientNum) throws Hl7Exception
    {
        if (StrUtil.isEmpty(classCode) && StrUtil.isEmpty(patientID))
        {
            log.info("该患者没有该文书下的病历");
            return getResultsDTO("该患者没有该文书下的病历", false, null);
        }
        List<Object> list = documentQuery.findEmrByPatientID(patientID, classCode,patientNum);
        if (ListUtil.isEmpty(list))
        {
            log.info("患者没有已书写的病历");
            return getResultsDTO("患者没有已书写的病历 ", true, null);
        }
        List<EmrWriterDTO> emrWriterList = ecm.convertDtoToList(list);
        log.info("获取患者病历成功");
        return getResultsDTO("获取患者病历成功 ", true, emrWriterList);
    }


    public ResultsDTO findDocumentFile(String docId) throws Hl7Exception
    {
        if (StrUtil.isEmpty(docId))
        {
            log.info("获取病历文件失败，docId为空");
            return getResultsDTO("获取病历文件失败，病历序号为空", true, null);
        }
        Document doc = baseQuery.findDocumentById(docId);
        EmrWriterDTO emrWriterDTO = ecm.convertDocToDto(doc);
        return getResultsDTO("获取患者病历成功 ", true, emrWriterDTO);
    }


    public ResultsDTO updateAudit(EmrModifyLogDTO emrModifyLog) throws Hl7Exception
    {
        if (null == emrModifyLog)
            return this.getResultsDTO("申请修改记录为空", false, null);
        String docId = emrModifyLog.getMedRecordId();
        Document doc = baseQuery.findDocumentById(docId);
        // 申请修改改变病历状态为草稿
        doc.setMedRecordsState(DataTypeUtil.getST("1"));
        Role role = baseQuery.findRoleById(Long.parseLong(emrModifyLog.getUpdateBy()));
        
        ActParticipation participation = getActFactory().newActParticipation();
        participation.setTypeCode(ParticipationType.WIT);
        participation.setCreateTime(DataTypeUtil.getTS(DateUtil.getDate()));
        if (StrUtil.isNotEmpty(emrModifyLog.getDesc()))
        {
            ED ed = DataTypeUtil.getED(emrModifyLog.getDesc());
            participation.setNoteText(ed); // 申请修改原因
        }
        if (null != doc)
        {
            doc.addParticipation(participation, role);
            em.merge(doc);
        }
        return this.getResultsDTO("申请修改添加成功", true, null);
    }


    public ResultsDTO findInPatientMacroInfoByPatientId(String patientId,String patientNum) throws Hl7Exception
    {
        if (StrUtil.isEmpty(patientId))
            return this.getResultsDTO("获取患者主诉信息成功", true, null);
        List<RimCoreEds> list = documentQuery.findInPatientMacroInfoByPatientId(patientId,patientNum);
        if (ListUtil.isNotEmpty(list))
        {
            String mcaroInfo = null;
            for (RimCoreEds eds : list)
            {
                if (null != eds && null != eds.getEdClob())
                {
                    ED ed = DataTypeUtil.getED(String.valueOf(eds.getEdClob()));
                    mcaroInfo = ed.stringValue();
                }
            }
            if (StrUtil.isNotEmpty(mcaroInfo))
            {
                return this.getResultsDTO("获取患者主诉信息成功", true, mcaroInfo);
            }
            else
                return this.getResultsDTO("获取患者主诉信息成功", true, null);
        }
        else
            return this.getResultsDTO("获取患者主诉信息未成功", true, null);
    }


    public ResultsDTO findDiagnosisListByPatientId(String patientId,String patientNum) throws Hl7Exception
    {
        List<Observation> list = documentQuery.findDiagnosisByPatientId(patientId,patientNum);
        List<EmrDiagnosisDTO> obsList = observationManager.converEmrDiagnosisDTOList(list);
        if (ListUtil.isNotEmpty(obsList))
        {
            return this.getResultsDTO("获取患者诊断信息成功", true, obsList);
        }
        return this.getResultsDTO("诊断信息为空", true, null);
    }


    public ResultsDTO findNotSignatureDocByPatientId(String patienId,String patientNum) throws Hl7Exception
    {
        // 判断患者一共书写了多少个文件
        List<Long> rctList = documentQuery.findAlreadyWriteDocByPatientId(patienId,patientNum);
        // 判断患者一共签名了多少个文件
        List<Long> escList = documentQuery.findAlreadySignatureDocByPatientId(patienId,patientNum);
        // 如果签名的文档总数比已经书写的总数要少，提醒患者有没有签名的文件
        if (ListUtil.isNotEmpty(rctList))
        {
            if (ListUtil.isNotEmpty(escList))
            {
                if (rctList.size() == escList.size())
                {
                    return this.getResultsDTO("该患者病历全部已经签名", true, "1");
                }
            }
            else
            {
                return this.getResultsDTO("该患者有病历没有签名", true, "0");
            }
        }
        return this.getResultsDTO("验证通过", true, "-1");
    }
    
    //修改病历基本信息
    private void modifyEmrBaseInfo(EmrWriterDTO emr,Document doc) throws Hl7Exception
    {
        //修改宏元素
        ecm.modifyMacro(doc,emr.getMacroContents());
        // 修改病历文件
        if (null != emr.getContents())
        {
            ED text = DataTypeUtil.getED(null, emr.getContents());
            doc.setText(text);
        }
    }
    
    private void constructParticipationList(Map<CS,Role> socopeMap,EmrWriterDTO emr) throws Hl7Exception
    {
        if(!socopeMap.isEmpty())
        {
            Set<CS> set = socopeMap.keySet();
            for(Iterator<CS> it = set.iterator();it.hasNext();)
            {
                CS typeCode = it.next();
                Role empRole = socopeMap.get(typeCode);
                ActParticipation part = getActFactory().newActParticipation();
                part.setTypeCode(typeCode);
                if(typeCode.equals(ParticipationType.RCT))
                {
                    if (StrUtil.isNotEmpty(emr.getMacroContents()))
                    {
                        // 患者入院记录中单独保存的json字符串
                        ED ed = DataTypeUtil.getED(emr.getMacroContents());
                        part.setNoteText(ed);
                    }
                    //住院次数
                    part.setSequenceNumber(DataTypeUtil.getINT(Long.valueOf(emr.getPatientNum())));
                }
                if(typeCode.equals(ParticipationType.ESC) 
                        || typeCode.equals(ParticipationType.DIS) 
                        || typeCode.equals(ParticipationType.CON))
                {
                    // 医生签名时间
                    part.setCreateTime(DataTypeUtil.getTS(DateUtil.getDate()));
                }
                addParticipation(empRole, part);
            }
        }
    }

}
